<?php

namespace App\Http\Services;

use App\Http\Model\Hint;
use App\Http\Model\OutJson;
use App\Http\Model\Room;
use App\Http\Model\RoomHostMicro;
use App\Http\Model\RoomVote;

/**
 * 房间投票
 */
class RoomVoteServices extends CommonServices
{
    private $model;
    private $roomModel;
    private $roomHostMicroModel;
    private $roomMsgServices;

    const STATUS_END = 2; //结束
    const STATUS_CANCEL = 3; //取消

    public function __construct()
    {
        parent::__construct();
        $this->model = new RoomVote();
        $this->roomModel = new Room();
        $this->roomHostMicroModel = new RoomHostMicro();
        $this->roomMsgServices = new RoomMsgServices();
    }

    /**
     * 读取投票信息
     *
     * @param $roomId int 房间ID
     * @return array
     */
    public function getInit($roomId)
    {
        $currentUser = $this->user->get_current_user();

        if (!$currentUser) {
            OutJson::outJsonNoData(Hint::LOGIN_OUT);
        }

        //检查房间是否投票中，未发起投票不允许投票
        $voteInfo = $this->model->getRoomVoteByRoomId($roomId);
        if (empty($voteInfo)) {
            return [];
        }

        //如果投票已结束，则不返回
        if (time() > $voteInfo['start_time'] + $voteInfo['vote_time']) {
            return [];
        }

        $voteInfo['current_time'] = time();

        //被投票用户列表
        list($voteInfo['user_list'], $voteCount) = $this->model->getRoomVoteRanking($voteInfo['vote_id'], $voteInfo['user_list']);

        //我的票数
        $myNum = $this->model->getRoomVotePollNum($voteInfo['vote_id'], $currentUser['user_id']);
        $diffNum = $voteInfo['vote_num'] - $myNum;
        $voteInfo['from_user_vote_num'] = $diffNum < 0 ? 0 : $diffNum;

        return $voteInfo;
    }

    /**
     * 发起投票
     *
     * @param $roomId int 房间ID
     * @param $type int 操作类型：1按人气票;2按钻石礼物
     * @param $topicId int 话题id
     * @param $voteNum int 票数
     * @param $voteTime int 投票时长（秒)
     * @param $toUserIds array 被投票的用户列表
     * @return array
     */
    public function startRoomVote($roomId, $type, $topicId, $voteNum, $voteTime, $toUserIds)
    {
        $currentUser = $this->user->get_current_user();

        if (!$currentUser) {
            OutJson::outJsonNoData(Hint::LOGIN_OUT);
        }

        //检查房间是否开启
        if (!$this->roomModel->get_opened($roomId)) {
            OutJson::outJsonNoData(Hint::ROOM_NOT_OPEN);
        }

        $roomInfo = $this->roomModel->get_room($roomId);

        //CBD房间才能发起投票
        if ($roomInfo['business_type'] != 1) {
            OutJson::outJsonNoData(Hint::ROOM_VOTE_BUSINESS_ERROR);
        }

        $roomRole = $this->roomModel->get_role($roomId, $currentUser['user_id']);
        $micUserId = $this->roomHostMicroModel->get_user_id($roomId);
        if ($roomRole == 0) {
            //普通用户不能发起投票
            OutJson::outJsonNoData(Hint::ROOM_VOTE_USER_ROLE_ERROR);
        } elseif ($roomRole == 1 && intval($micUserId) != $currentUser['user_id']) {
            //普通管理不是主持不能发起投票
            OutJson::outJsonNoData(Hint::ROOM_VOTE_USER_ROLE_ERROR);
        }

        $voteInfo = $this->model->getRoomVoteByRoomId($roomId);
        if ($voteInfo) {
            //如果投票数据已存在，且已经过期，需要结束掉。
            $endTime = $voteInfo['start_time'] + $voteInfo['vote_time'] + 10;
            if (time() > $endTime) {
                //结束投票，更新投票结果
                $this->model->endRoomVote($voteInfo['vote_id'], self::STATUS_END);
            } else {
                //不能重复发起投票
                OutJson::outJsonNoData(Hint::ROOM_VOTE_IS_RUNING);
            }
        }

        //写数据库、写redis
        $create = $this->model->startRoomVote($roomId, $type, $topicId, $voteNum, $voteTime, $currentUser['user_id'], $toUserIds);
        if (empty($create)) {
            OutJson::outJsonNoData(Hint::ROOM_VOTE_OPTION_FAIL);
        }

        //向房间内广播通知消息
        $this->roomMsgServices->sendStartRoomVote($roomId, $create);

        return $create;
    }

    /**
     * 取消投票
     *
     * @param $voteId string 投票ID
     * @return array
     */
    public function cancelRoomVote($voteId)
    {
        $currentUser = $this->user->get_current_user();

        if (!$currentUser) {
            OutJson::outJsonNoData(Hint::AUTH_ERROR);
        }

        //检查房间是否投票中
        $voteInfo = $this->model->getRoomVote($voteId);
        if (empty($voteInfo)) {
            OutJson::outJsonNoData(Hint::ROOM_VOTE_NOT_EXISTS);
        }

        $roomId = $voteInfo['room_id'];

        $roomRole = $this->roomModel->get_role($roomId, $currentUser['user_id']);
        $micUserId = $this->roomHostMicroModel->get_user_id($roomId);
        if ($roomRole == 0) {
            //普通用户不能操作
            OutJson::outJsonNoData(Hint::ROOM_VOTE_USER_ROLE_ERROR);
        } elseif ($roomRole == 1 && intval($micUserId) != $currentUser['user_id']) {
            //普通管理不是主持不能操作
            OutJson::outJsonNoData(Hint::ROOM_VOTE_USER_ROLE_ERROR);
        }

        //结束投票，更新投票结果
        $this->model->endRoomVote($voteId, self::STATUS_CANCEL);

        //向房间内广播通知消息
        $text = "管理员{$currentUser['nickname']}已取消本场投票PK";
        $this->roomMsgServices->sendCancelRoomVote($roomId, $voteId, $text);

        return [];
    }

    /**
     * 结束投票
     *
     * @param $voteId string 投票ID
     * @return bool
     */
    public function endRoomVote($voteId)
    {
        //检查房间是否投票中
        $voteInfo = $this->model->getRoomVote($voteId);
        if (empty($voteInfo)) {
            write_log("roomVote", 'error', Hint::$Msg[Hint::ROOM_VOTE_NOT_EXISTS]);
            return false;
        }

        //排行榜排序
        list($voteInfo['user_list'], $voteCount) = $this->model->getRoomVoteRanking($voteId, $voteInfo['user_list']);

        //结束投票，更新投票结果
        $this->model->endRoomVote($voteId, self::STATUS_END);

        if ($voteCount == 0) {
            $msg = "很遗憾，无人参与投票，本次PK无结果～";
        } else {
            $type = $voteInfo['type'] == 1 ? "人气PK" : "钻石礼物PK";
            if (count($voteInfo['user_list']) == 2) {
                $nickname = $voteInfo['user_list'][0]['win'] == 1 ? $voteInfo['user_list'][0]['nickname'] : $voteInfo['user_list'][1]['nickname'];
            } else {
                $nickname = $voteInfo['user_list'][0]['nickname'];
            }

            $msg = "恭喜" . $nickname . "在本轮" . $type . "中获胜";
        }

        //向房间内广播通知消息
        $this->roomMsgServices->sendEndRoomVote($voteInfo['room_id'], $voteInfo, $msg);

        return true;
    }


    /**
     * 用户投票(人气票)
     *
     * @param $voteId string 投票ID
     * @param $toUserId int 投票给用户ID
     * @return array
     */
    public function pollRoomVote($voteId, $toUserId)
    {
        $currentUser = $this->user->get_current_user();

        if (!$currentUser) {
            OutJson::outJsonNoData(Hint::AUTH_ERROR);
        }

        //不能为自己投票
        if ($currentUser['user_id'] == $toUserId) {
            OutJson::outJsonNoData(Hint::ROOM_VOTE_USER_MYSELF);
        }

        //检查房间是否投票中，未发起投票不允许投票
        $voteInfo = $this->model->getRoomVote($voteId);
        if (empty($voteInfo)) {
            OutJson::outJsonNoData(Hint::ROOM_VOTE_NOT_EXISTS);
        }

        //如果过期，则不写入
        if (time() > $voteInfo['start_time'] + $voteInfo['vote_time']) {
            OutJson::outJsonNoData(Hint::ROOM_VOTE_TIME_END);
        }

        //检查被投票者是不是在投票人列表中
        $toUserIds = array_column($voteInfo['user_list'], 'user_id');
        if (!in_array($toUserId, $toUserIds)) {
            OutJson::outJsonNoData(Hint::ROOM_VOTE_USER_NOT_EXISTS);
        }

        //检查投票人剩余票数
        $myNum = $this->model->getRoomVotePollNum($voteId, $currentUser['user_id']);

        $diffNum = $voteInfo['vote_num'] - $myNum;

        if ($diffNum <= 0) {
            OutJson::outJsonNoData(Hint::ROOM_VOTE_POLL_EMPTY);
        }

        //开始投票
        $data = $this->model->pollRoomVote($voteId, $currentUser['user_id'], $toUserId);
        if (!$data) {
            OutJson::outJsonNoData(Hint::ROOM_VOTE_OPTION_FAIL);
        }

        $voteInfo['current_time'] = time();

        //被投票用户列表
        list($voteInfo['user_list'], $voteCount) = $this->model->getRoomVoteRanking($voteId, $voteInfo['user_list']);
        $this->roomMsgServices->sendPollRoomVote($currentUser['user_id'], $voteInfo, $diffNum - 1);

        return [];
    }

    /**
     * 钻石投票
     *
     * @param $roomId int 房间id
     * @param $toUserIds array 投票给谁
     * @param $voteNum int 票数
     * @return bool
     */
    public function roomVoteDiamondPoll($roomId, $userId, $toUserIds, $voteNum)
    {
        try {
            $voteInfo = $this->model->getRoomVoteByRoomId($roomId);
            if (empty($voteInfo)) {
                return true;
            }

            //人气票不计入
            if ($voteInfo['type'] != 2) {
                return true;
            }

            //如果过期，则不写入
            if (time() > $voteInfo['start_time'] + $voteInfo['vote_time']) {
                return true;
            }

            //只保留能投票的用户
            $voteInfoUserIds = array_column($voteInfo['user_list'], 'user_id');
            $intersectUserIds = array_intersect($voteInfoUserIds, $toUserIds);
            if (empty($intersectUserIds)) {
                return true;
            }

            //开始投票
            foreach ($intersectUserIds as $uid) {
                $this->model->pollRoomVote($voteInfo['vote_id'], $userId, $uid, $voteNum);
            }

            $voteInfo['current_time'] = time();

            //发送消息
            list($voteInfo['user_list'], $voteCount) = $this->model->getRoomVoteRanking($voteInfo['vote_id'], $voteInfo['user_list']);
            $this->roomMsgServices->sendPollRoomVote($userId, $voteInfo, 0);

            return true;
        } catch (\Throwable $exception) {
            write_log('roomVote', 'error', $exception->getMessage());
        }
    }

    /**
     * 读取话题列表
     * @return array
     */
    public function topics()
    {
        return $this->model->getTopics();
    }

    /**
     * 添加/编辑 话题
     * @return bool
     */
    public function editTopic($id, $title)
    {
        if (empty($id)) { //添加话题
            $result = $this->model->addTopic($title);
        } else { //修改话题
            $result = $this->model->editTopic($id, $title);
        }
        return intval($result);
    }

    /**
     * 添加话题
     * @return int
     */
    public function deleteTopic($id)
    {
        return $this->model->deleteTopic($id);
    }

}